import 'dart:io';

import 'package:adb_tool/base/base_view_model.dart';
import 'package:adb_tool/data_helper.dart';
import 'package:adb_tool/ext/dialog_ext.dart';
import 'package:archive/archive_io.dart';
import 'package:dio/dio.dart';
import 'package:flutter/material.dart';
import 'package:path_provider/path_provider.dart';
import 'package:process_run/shell.dart';

import '../../common/app.dart';
import '../../model/devices_model.dart';
import '../../widgets/list_filter_dialog.dart';
import '../../widgets/pop_up_menu_button.dart';

class MainViewModel extends BaseViewModel {
  final List<String> _leftTabs = ["首页", "文件管理", "图片管理", "日志监控"];

  PopUpMenuButtonViewModel<DevicesModel> devicesViewModel = PopUpMenuButtonViewModel();
  ListFilterController packageNameController = ListFilterController();
  int _index = 0;

  int get index => _index;

  List<String> get leftTabs => _leftTabs;
  String buildNumber = "1.0.1";

  void changeIndex(int index) {
    _index = index;
    notifyListeners();
  }

  MainViewModel(BuildContext context) : super(context) {
    devicesViewModel.addListener(() {
      if (devicesViewModel.selectValue != null) {
        App().setDeviceId(deviceId);
        getInstalledApp(deviceId);
      }
    });
    App().eventBus.on<String>().listen((event) {
      if (event == "refresh") {
        getInstalledApp(deviceId);
      }
    });

  }

  List<String> packageNameList = [];

  /// 设备id
  String get deviceId => devicesViewModel.selectValue?.id ?? "";

  /// 包名
  String packageName = "";

  init() async {
    await checkAdb();
    if (adbPath.isNotEmpty) {
      await getDeviceList();
    }

  }

  /// 选择调试应用
  packageSelect(BuildContext context) async {
    if (packageNameList.isEmpty) {
      return;
    }
    packageNameController.show(
      context,
      packageNameList,
      packageName,
      itemClickCallback: (context, value) {
        packageName = value;
        App().setPackageName(packageName);
        notifyListeners();
        Navigator.of(context).pop();
      },
    );
  }

  refresh() async {
    await getDeviceList();
    await getInstalledApp(deviceId);
  }

  /// 获取设备列表
  getDeviceList() async {
    var devices = await execAdb(['devices']);
    if (devices == null) {
      clearData();
      return;
    }
    List<DevicesModel> list = [];
    for (var value in devices.outLines) {
      if (value.contains("List of devices attached")) {
        continue;
      }
      if (value.contains("device")) {
        var deviceLine = value.split("\t");
        if (deviceLine.isEmpty) {
          continue;
        }
        var device = deviceLine[0];
        var brand = await getBrand(device);
        var model = await getModel(device);
        list.add(DevicesModel(brand, model, device));
      }
    }
    if (list.isEmpty) {
      clearData();
      return;
    } else {
      App().getDeviceId().then((value) {
        if (value.isNotEmpty) {
          devicesViewModel.selectValue = list.firstWhere((element) => element.id == value, orElse: () => list.first);
        } else {
          devicesViewModel.selectValue = list.first;
        }
      });
    }
    devicesViewModel.list = list;
  }

  clearImageCache() async {
    showAlertDialog(
        context: context,
        content: "确定要清理缓存吗？",
        cancelText: "取消",
        onConfirm: () async {
          var savePath = ((await getApplicationSupportDirectory()).path) + "/$deviceId-images";
          var file = Directory(savePath);
          var exists = await file.exists();
          if (exists) {
            try {
              await file.list().forEach((element) {
                element.delete();
              });
              // await file.delete();
              showResultDialog(content: "清理成功");
            } catch (e) {
              showResultDialog(content: "清理失败：" + e.toString());
            }
          }
        });
  }

  /// 获取设备品牌
  Future<String> getBrand(String device) async {
    var brand = await execAdb(['-s', device, 'shell', 'getprop', 'ro.product.brand']);
    if (brand == null) return "";
    var outLines = brand.outLines;
    if (outLines.isEmpty) {
      return device;
    } else {
      return outLines.first;
    }
  }

  /// 获取设备型号
  Future<String> getModel(String device) async {
    var model = await execAdb(['-s', device, 'shell', 'getprop', 'ro.product.model']);
    if (model == null) return "";
    var outLines = model.outLines;
    if (outLines.isEmpty) {
      return device;
    } else {
      return outLines.first;
    }
  }

  /// 获取adb路径
  checkAdb() async {
    adbPath = await App().getAdbPath();
    if (adbPath.isNotEmpty && await File(adbPath).exists()) {
      return;
    }
    var executable = Platform.isWindows ? "where" : "which";
    var result = await exec(executable, ['adb']);
    if (result != null && result.exitCode == 0) {
      adbPath = result.stdout.toString().trim();
      App().setAdbPath(adbPath);
      return;
    }
    adbPath = await downloadAdb();
    if (adbPath.isNotEmpty) {
      App().setAdbPath(adbPath);
    }
  }

  /// 下载adb文件
  Future<String> downloadAdb() async {
    showLoading(text: "下载adb文件中...");
    var directory = await getTemporaryDirectory();
    var downloadPath = directory.path + Platform.pathSeparator + "platform-tools" + Platform.pathSeparator;
    var url = DataHelper.getAdbDownLoadUrl();
    if (Platform.isMacOS) {
      var filePath = downloadPath + "platform-tools-latest.zip";
      var response = await Dio().download(url, filePath);
      showLoading(text: "");
      if (response.statusCode == 200) {
        return unzipPlatformToolsFile(filePath);
      }
    }
    return "";
  }

  /// 解压并删除adb文件
  Future<String> unzipPlatformToolsFile(String unzipFilePath) async {
    var libraryDirectory = await getApplicationSupportDirectory();
    var savePath = libraryDirectory.path + Platform.pathSeparator + "adb" + Platform.pathSeparator;
    if (Platform.isWindows) {
      final inputStream = InputFileStream(unzipFilePath);
      final archive = ZipDecoder().decodeBuffer(inputStream);
      extractArchiveToDisk(archive, savePath);
    } else {
      await exec("rm", ["-rf", savePath]);
      await exec("unzip", [unzipFilePath, "-d", savePath]);
      await exec("rm", ["-rf", unzipFilePath]);
    }
    var adbPath = "${savePath}platform-tools${Platform.pathSeparator}adb";
    return Platform.isWindows ? "$adbPath.exe" : adbPath;
  }

  /// 获取已安装的应用
  Future<void> getInstalledApp(String devices) async {
    var installedApp = await execAdb(['-s', devices, 'shell', 'pm', 'list', 'packages', '-3']);
    if (installedApp == null) return;
    var outLines = installedApp.outLines;
    packageNameList = outLines.map((e) {
      return e.replaceAll("package:", "");
    }).toList();
    packageNameList.sort((a, b) => a.compareTo(b));
    if (packageNameList.isNotEmpty) {
      /// 将当前获取焦点的应用设备默认调试应用
      var _packageName = await getCurrentPackage(devices);
      if (_packageName.isNotEmpty) {
        packageName =
            packageNameList.firstWhere((element) => element == _packageName, orElse: () => packageNameList.first);
      } else {
        /// 当目前焦点是在系统应用的时候就选择之前缓存的
        App().getPackageName().then((value) {
          if (value.isNotEmpty) {
            packageName =
                packageNameList.firstWhere((element) => element == value, orElse: () => packageNameList.first);
          } else {
            packageName = packageNameList.first;
          }
        });
      }
    }
  }

  Future<String> getCurrentPackage(String devices) async {
    var focusedPackageName = "";
    var currentPackage =
        await execAdb(['-s', devices, 'shell', 'dumpsys', 'window', 'w', '|', 'grep', 'mCurrentFocus']);
    if (currentPackage != null) {
      var outText = currentPackage.outText;
      var substring = outText.substring(outText.lastIndexOf("{"), outText.lastIndexOf("}") + 1);
      var split = substring.split(" ");
      substring = split[split.length - 1];

      if (substring.contains('/')) {
        focusedPackageName = substring.split('/')[0];
      }
      print("当前包名:" + focusedPackageName);
    }
    return focusedPackageName;
  }

  /// 清理设备数据，应用数据
  void clearData() {
    devicesViewModel.selectValue = null;
    devicesViewModel.list.clear();
    packageName = "";
    packageNameList.clear();
  }
}
